package cn.jinjimi.base.util;

import android.text.TextUtils;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 */
public class URLUtil {

    private static final String TAG = URLUtil.class.getSimpleName();

    /**
     * 在URL上添加或更新参数
     */
    public static String appendParam(String url, String key, String value, boolean replaceOrigin) {
        Map<String, String> params = new LinkedHashMap<>();
        params.put(key, value);
        return appendParam(url, params, replaceOrigin);
    }

    public static String appendParam(String url, String key, String value) {
        return appendParam(url, key, value, false);
    }

    /**
     * 在URL中添加或更新参数集合
     *
     * @param url
     * @param params
     * @return
     */
    public static String appendParam(String url, Map<String, String> params, boolean replaceOrigin) {

        URI uri = URLUtil.create(url);

        if (uri == null) {
            return "";
        }

        Map<String, String> current = getParams(decode(url));

        //udpate url param.
        if (current != null) {
            for (String key : current.keySet()) {
                boolean containsKey = params.containsKey(key);
                boolean emptyValue = containsKey && TextUtils.isEmpty(params.get(key));
                if (!containsKey || !replaceOrigin || emptyValue) {
                    params.put(key, current.get(key));
                }
            }
        }

        //normal start here
        String scheme = uri.getScheme();
        if (StringUtils.isEmpty(scheme)) {
            return "";
        }
        StringBuilder result = new StringBuilder(scheme);
        result.append("://").append(uri.getHost());

        if (uri.getPort() != -1)
            result.append(":").append(uri.getPort());

        result.append(uri.getPath()).append("?");

        for (String key : params.keySet()) {
            result.append(key).append("=").append(params.get(key)).append("&");
        }

        if (uri.getFragment() != null) {
            result.append("#").append(uri.getFragment());
        }

        LogUtil.d(TAG, result.toString());

        return result.toString();

    }

    public static String appendParam(String url, Map<String, String> params) {
        return appendParam(url, params, false);
    }


    /**
     * 获取URL中的值
     *
     * @param url
     * @param key
     * @return
     */
    public static String getParamValue(String url, String key) {
        if (url == null) {
            return null;
        }

        Pattern p = Pattern.compile("([\\?|&])" + key + "=([^&?]*)", Pattern.CASE_INSENSITIVE);

        Matcher matcher = p.matcher(url);
        if (matcher.find()) {
            return decode(matcher.group(2));
        }

        return null;
    }

    /**
     * 获取URL中的键值对
     *
     * @param decodedUrl
     * @return
     */
    public static Map<String, String> getParams(String decodedUrl) {
        Pattern p = Pattern.compile("([\\?|&])(.+?)=([^&?#]*)", Pattern.CASE_INSENSITIVE);
        Map<String, String> kvs = new LinkedHashMap<>();

        Matcher matcher = p.matcher(decodedUrl);
        while (matcher.find()) {
            kvs.put(matcher.group(2), encode(matcher.group(3)));
        }
        return kvs;
    }

    public static boolean findParams(String url) {
        Pattern p = Pattern.compile("([\\?|&])(.+?)=([^&?#]*)", Pattern.CASE_INSENSITIVE);
        return p.matcher(url).find();
    }

    /**
     * 去除URL中的空格
     *
     * @param url
     * @return
     */
    public static URI create(String url) {
        if (StringUtils.isEmpty(url)) {
            return null;
        }

        try {
            return URI.create(decode(url.trim()));
        } catch (IllegalArgumentException e) {
            return createByIllegalUrl(url);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 出现illegalException时采用以下方法解析uri
     *
     * @param url
     * @return
     */
    public static URI createByIllegalUrl(String url) {
        try {
            String scheme = url.substring(0, url.indexOf("://"));
            String schemeSpecificPart = url.substring(url.indexOf("//"), url.contains("#") ? url.lastIndexOf("#") : url.length());
            String fragment = url.contains("#") ? url.substring(url.lastIndexOf("#")) : null;
            try {
                return new URI(scheme, schemeSpecificPart, fragment);
            } catch (URISyntaxException e1) {
                e1.printStackTrace();
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }

    public static String removeParam(String url, String key) {
        if (url != null && key != null) {
            return url.replaceAll("([\\?|&])" + key + "=([^&?#]*)", "");
        }
        return null;
    }

    public static boolean isNewUrl(String url, String url2) {
        return url != null && url2 != null && !url2.equals(url.replaceAll("#(.*)$", ""));
    }

    /**
     * try to decode twice
     *
     * @param url
     * @return
     */
    public static String decode(String url) {
        String result = url;

        try {
            if (result != null && result.contains("%")) {
                result = URLDecoder.decode(result.trim(), "UTF-8");
                if (result != null && result.contains("%")) {
                    return URLDecoder.decode(result, "UTF-8");
                }
            }
        } catch (UnsupportedEncodingException e) {
            //e.printStackTrace();
        }

        return result;
    }

    public static String encode(String url) {
        try {
            return URLEncoder.encode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            //e.printStackTrace();
        }
        return url;
    }
}
